/*
	TraitOrbit.cpp
	(c)2004 Palestar Inc, Richard Lyle
*/


#include "TraitOrbit.h"
#include "GameContext.h"

//----------------------------------------------------------------------------

IMPLEMENT_FACTORY( TraitOrbit, Trait );
REGISTER_FACTORY_KEY( TraitOrbit, 4780777174566942733 );

BEGIN_PROPERTY_LIST( TraitOrbit, Trait )
	ADD_TRANSMIT_UPDATE_PROPERTY( m_pOrbiting );
	ADD_TRANSMIT_UPDATE_PROPERTY( m_fOrbitDistance );
	ADD_TRANSMIT_UPDATE_PROPERTY( m_fOrbitPosition );
	ADD_TRANSMIT_UPDATE_PROPERTY( m_fOrbitVelocity );
END_PROPERTY_LIST();

TraitOrbit::TraitOrbit()
	: m_fOrbitDistance( 0 ), m_fOrbitPosition( 0 ), m_fOrbitVelocity( 0 )
{}

//----------------------------------------------------------------------------

void TraitOrbit::simulate( dword nTick )
{
	int nElapsed = nTick - parent()->tick();
	if ( nElapsed > 0 )
		dynamics( nElapsed );
	Trait::simulate( nTick );
}

void TraitOrbit::setOrbit( Noun * pOrbit, float fDistance, float fPosition, float fVelocity, int nTicks /*= 0*/ )
{
	m_pOrbiting = pOrbit;
	m_fOrbitDistance = fDistance;
	m_fOrbitPosition = fPosition;
	m_fOrbitVelocity = fVelocity;
	m_vLastPosition = parent()->position();

	// set the world position for our parent now.. call dynamics() even if nTicks is 0, because it
	// sets other variables such as the base velocity... etc
	dynamics( nTicks );
}

void TraitOrbit::breakOrbit()
{
	m_pOrbiting = NULL;
}

void TraitOrbit::dynamics( int nTicks )
{
	// update the position if in orbit
	if ( m_pOrbiting.valid() && parent()->isRootNoun() )
	{
		float fElapsed = TICK_DURATION_S * nTicks;
		// update the orbit position
		m_fOrbitPosition += m_fOrbitVelocity * fElapsed;

		// calculate our new zone position
		Vector3 vPosition = m_pOrbiting->zonePosition( parent()->zone() ) + 
			(Vector3( sinf( m_fOrbitPosition ), 0, cosf( m_fOrbitPosition ) ) * m_fOrbitDistance );

		// set our world position
		parent()->setPosition( vPosition );
		parent()->invalidateWorld();

		if ( fElapsed > 0.0f )
		{
			parent()->setBaseVelocity( (vPosition - m_vLastPosition) / fElapsed );
			m_vLastPosition = vPosition;
		}
	}
}

//----------------------------------------------------------------------------
//EOF
